package runner;

import gui.Guimap;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import java.util.Set;

import pathfinding.Pathfinding;

import buffs.Buff;

import main.Coord;
import main.TDMap;
import main.Tickable;

public class Enemy extends Observable implements Tickable, Observer {
	Coord c;
	private List<Coord> path;
	private int atpos;
	private boolean dead=false;
	private boolean fin=false;
	private int hp;
	private TDMap map;
	private EnemyTemplate et;
	private Set<Buff> buffs;

	public Enemy(TDMap map, Coord start, EnemyTemplate et) {
		this.map = map;
		this.et = et;
		start.convert(Guimap.TILE_WIDTH, Guimap.TILE_HEIGHT);
		c = start;
		path = new ArrayList<Coord>();
		for (Coord c: map.getPath()) {
			path.add(new Coord(c.x*Guimap.TILE_WIDTH+Guimap.TILE_WIDTH/2, c.y*Guimap.TILE_HEIGHT+Guimap.TILE_HEIGHT/2));
		}
		atpos=0;
		hp=et.maxhp;
		buffs = new HashSet<Buff>();
	}
	
	@Override
	public void tick() {
		EnemyTemplate t = new EnemyTemplate(et);
		for (Buff b: buffs) {
			b.ticked(t);
		}
		if (dead || fin)
			return;
		
		if (path.get(atpos).distanceTo(c) <= t.speed) {
			atpos++;
			if (atpos >= path.size()) {
				fin=true;
				this.setChanged();
				this.notifyObservers();
				return;
			}
		}
		c.x = c.x+ (int) (Math.cos(c.angle(path.get(atpos)))*t.speed);
		c.y = c.y+ (int) (Math.sin(c.angle(path.get(atpos)))*t.speed);
	}
	
	public int getHP() {
		return hp>0? hp: 0;
	}
	public int maxHP() {
		return et.maxhp;
	}

	public Coord getPos() {
		return c;
	}

	public void attack(int power) {
		EnemyTemplate t = new EnemyTemplate(et);
		for (Buff b: buffs) {
			b.attacked(t);
		}
		hp -= power*(1/Math.sqrt(t.armor));
		if (hp < 0 && !dead) {
			dead=true;
			this.setChanged();
			this.notifyObservers();
		}
	}

	
	public boolean isDead() {
		return dead;
	}
	public boolean finished() {
		return fin;
	}

	@Override
	public void update(Observable obs, Object arg1) {
		TDMap map = (TDMap)obs;
		Coord startpos = new Coord(c.x/Guimap.TILE_WIDTH, c.y/Guimap.TILE_HEIGHT);
		Coord end = path.get(path.size()-1);
		end = new Coord(end.x/Guimap.TILE_WIDTH, end.y/Guimap.TILE_HEIGHT);
		List<Coord> bestPath = Pathfinding.find(startpos, end, map.getPathMap());
		path = new ArrayList<Coord>();
		for (Coord c: bestPath) {
			path.add(new Coord(c.x*Guimap.TILE_WIDTH+Guimap.TILE_WIDTH/2, c.y*Guimap.TILE_HEIGHT+Guimap.TILE_HEIGHT/2));
		}
		atpos= path.size()>1? 1: 0;
	}

	public EnemyTemplate getTemplate() {
		return et;
	}
	
	public void addBuff(Buff b) {
		for (Buff bu: buffs) {
			if (bu.getClass() == b.getClass())
				return;
			else
				System.out.println(bu.getClass() +" != "+ b.getClass());
		}
		buffs.add(b);
	}

	public void addBuffs(Set<Buff> buffs) {
		for (Buff b: buffs) {
			addBuff(b);
		}
	}
}
